#include "MC12.h"

unsigned char I2C_ADDR[4]={0x68,0x69,0x6A,0x6B}; 


/**-----------------------------------------------------------------------
  * @brief  配置通道分频系数
  * @param  fin_div:外部输入频率分频;fref_div:内部参考时钟分频；
    例：MC12_SetFreDiv(1,1)配置外部输入频率部分频，内部参考频率不分频;
  * @retval 是否传输成功
-------------------------------------------------------------------------*/
int MC12_SetFreDiv(uint16_t fin_div,uint8_t fref_div)
{
	I2C_Trans_Type I2C_Result ;
	if( fin_div==1 || fin_div==2 || fin_div==4 || fin_div==8 || fin_div==16 || fin_div==32
		|| fin_div==64 || fin_div==128 || fin_div==256 )
	{
		MC1112_I2C_Transmit(I2C_ADDR[1],FIN_DIV_CH1,MC_Log2(fin_div)<<4);
		MC1112_I2C_Transmit(I2C_ADDR[1],FREF_DIV_CH1,(fref_div-1));
		MC1112_I2C_Transmit(I2C_ADDR[1],FIN_DIV_CH0,MC_Log2(fin_div)<<4);
		I2C_Result = MC1112_I2C_Transmit(I2C_ADDR[1],FREF_DIV_CH0,(fref_div-1));
		if(I2C_Result != GPIOI2C_XFER_LASTACK)return 0;
	}
	else
	{
		return 0;
	} 
	
	return 1;

   
}

/**-----------------------------------------------------------------------
  * @brief  配置通道驱动电流
  * @param  drive_i：需要配置的驱动电流；
    MC12_SetDrive_I(DRIVE_I_04mA),配置驱动电流为0.4ma;
  * @retval 是否传输成功
-------------------------------------------------------------------------*/
int MC12_SetDrive_I(Drive_I_Type drive_i)
{
	I2C_Trans_Type I2C_Result;
	
	MC1112_I2C_Transmit(I2C_ADDR[1],DRIVE_I_CH1,drive_i);
	I2C_Result = MC1112_I2C_Transmit(I2C_ADDR[1],DRIVE_I_CH0,drive_i);
	if(I2C_Result != GPIOI2C_XFER_LASTACK) return 0;
	return 1;
	

}


/**-----------------------------------------------------------------------
  * @brief  配置测量通道数
  * @param  ch：需要开启通道的通道数，3表示开启双通道,0表示关闭双通道；
    MC12_SetChannel(1),开启第1通道;
  * @retval 是否传输成功
-------------------------------------------------------------------------*/
int MC12_SetChannel(uint8_t ch)
{
	uint8_t CHX=0;
	I2C_Trans_Type I2C_Result;
	if(ch>3)ch=3;
	CHX = ch<<6;

	I2C_Result = MC1112_I2C_Transmit(I2C_ADDR[1],CHX_EN,CHX);
	if(I2C_Result != GPIOI2C_XFER_LASTACK)return 0;
	return 1;
}


/**-----------------------------------------------------------------------
  * @brief  配置双通道报警/报警解除阈值
  * @param  TH：DATA报警阈值;TL:DATA解除报警阈值,
  * @retval 是否传输成功
-------------------------------------------------------------------------*/
int MC12_SetAlert(uint16_t TH , uint16_t TL)
{
	I2C_Trans_Type I2C_Result;

	MC1112_I2C_Transmit(I2C_ADDR[1],TH_MSB,(uint8_t)(TH>>8));
	MC1112_I2C_Transmit(I2C_ADDR[1],TH_LSB,(uint8_t)(TH&0XFF));
	MC1112_I2C_Transmit(I2C_ADDR[1],TL_MSB,(uint8_t)(TL>>8));
	I2C_Result = MC1112_I2C_Transmit(I2C_ADDR[1],TL_LSB,(uint8_t)(TL&0XFF));
	if(I2C_Result != GPIOI2C_XFER_LASTACK)return 0;
	return 1;
		

}

/**-----------------------------------------------------------------------
  * @brief  MC12启动软复位
  * @param  None
  * @retval 是否传输成功
-------------------------------------------------------------------------*/
int MC12_Reset(void)
{
	I2C_Trans_Type  I2C_Result;
	I2C_Result = MC1112_I2C_Transmit(I2C_ADDR[1],MC_RESET,0x7A);
	MY_DELAY_MS(10);//等待软复位
	if(I2C_Result != GPIOI2C_XFER_LASTACK)return 0;
	return 1;

}

/**-----------------------------------------------------------------------
  * @brief  MC12配置抗尖峰滤波
  * @param  en：开关滤波器
  * @retval 是否传输成功
-------------------------------------------------------------------------*/
int MC12_Filter_EN(uint8_t en)
{
	I2C_Trans_Type  I2C_Result;
	I2C_Result = MC1112_I2C_Transmit(I2C_ADDR[1],GLITCH_FILTER_EN,en);	
	if(I2C_Result != GPIOI2C_XFER_LASTACK)return 0;
	return 1;
}

/**-----------------------------------------------------------------------
  * @brief  MC12配置测量模式
  * @param  mode：选择测量模式
  * @retval 是否传输成功
-------------------------------------------------------------------------*/
int MC12_ConfigMode(Measure_mode mode)
{
	I2C_Trans_Type  I2C_Result;
	uint8_t cfg;
	MC1112_I2C_Receive(I2C_ADDR[1],CFG,&cfg);	
	cfg &= ~(Config_Mode_Pos);
	cfg |= mode;
	I2C_Result = MC1112_I2C_Transmit(I2C_ADDR[1],CFG,cfg);	
	if(I2C_Result != GPIOI2C_XFER_LASTACK)return 0;
	return 1;
}

#define SCNT_VALUE 0x0F		//配置建立时间，0x0F*16/2.4Mhz = 100us
#define RCNT_VALUE 0x5CD0	//配置通道计数时间，0x5CD0/2.4Mhz = 9.9ms
#define Drive_I_VALUE DRIVE_I_CH0_80mA	//配置驱动电流8mA
#define Fin_Div_VALUE 128	//配置外部输入频率128分频
#define Fref_Div_VALUE 1	//配置内部参考时钟不分频
#define Channel_Num 3		//配置开启双通道,0:关闭所有通道，1：开启第一通道，2：开启第二通道，3：开启双通道
#define Filter_en 1			//配置开启抗尖峰滤波器使能
/**-----------------------------------------------------------------------
  * @brief  MC12初始化函数
  * @param  *wait_time:测量等待时间
  * @retval 是否传输成功
-------------------------------------------------------------------------*/
int MC12_Init(int *wait_time)
{
	uint8_t data_msb,data_lsb,ch_en;
	I2C_Trans_Type I2C_Result;
	
	MC12_Reset();	//芯片软复位，恢复初始值

	MC12_ConfigMode(OS_SD_Stop_Trans);	//配置停止测量
	MY_DELAY_MS(20);		//等待双通道此次测量完成
	MC12_SetDrive_I(Drive_I_VALUE);	//配置驱动电流为8ma
	MC12_SetFreDiv(Fin_Div_VALUE,Fref_Div_VALUE);	//配置输入频率128分频，内部参考采样时钟不分频
	MC12_SetChannel(Channel_Num);		//配置双通道开启
	MC12_Filter_EN(Filter_en);			//开启滤波器

	MC1112_I2C_Transmit(I2C_ADDR[1],RCNT_CH0_MSB,RCNT_VALUE>>8);		//配置通道0计数时间
	MC1112_I2C_Transmit(I2C_ADDR[1],RCNT_CH0_LSB,RCNT_VALUE&0XFF);
	MC1112_I2C_Transmit(I2C_ADDR[1],RCNT_CH1_MSB,RCNT_VALUE>>8);		//配置通道1计数时间
	MC1112_I2C_Transmit(I2C_ADDR[1],RCNT_CH1_LSB,RCNT_VALUE&0XFF);

	MC1112_I2C_Transmit(I2C_ADDR[1],SCNT_CH0,SCNT_VALUE);		//配置通道0建立时间
	MC1112_I2C_Transmit(I2C_ADDR[1],SCNT_CH1,SCNT_VALUE);		//配置通道1建立时间

	//清除statu标志
	MC1112_I2C_Receive(I2C_ADDR[1],DATA_CH0_MSB,&data_msb);
	MC1112_I2C_Receive(I2C_ADDR[1],DATA_CH0_LSB,&data_lsb);
	MC1112_I2C_Receive(I2C_ADDR[1],DATA_CH1_MSB,&data_msb);
	MC1112_I2C_Receive(I2C_ADDR[1],DATA_CH1_LSB,&data_lsb);
	I2C_Result = MC1112_I2C_Receive(I2C_ADDR[1],CHX_EN,&ch_en);
	if(I2C_Result != GPIOI2C_XFER_LASTNACK)return 0;
	if((ch_en>>6)==0x03)*wait_time =(int)((((float)SCNT_VALUE*16+(float)RCNT_VALUE+4)/(CLKIN*1000))*2+1);		//计算双通道等待时间，1ms裕度，单位ms，T=2*（Tset+Tcnt）=2*（SCNT*16+RCNT+4）/Fref
	else *wait_time =(int)((((float)SCNT_VALUE*16+(float)RCNT_VALUE+4)/(CLKIN*1000))+1);
	
	return 1;

}


/**-----------------------------------------------------------------------
  * @brief  MC12开启单次测量双通道频率
  * @param  *F0:通道0频率值；*F1：通道1频率值；wait_time：测量等待时长
  * @retval 是否传输成功
-------------------------------------------------------------------------*/
int MC12_Measure(float *F0, float *F1 ,int wait_time)
{
	uint8_t sta;
	I2C_Trans_Type I2C_Result;
	uint32_t timeout;
	
	
	uint8_t data_msb,data_lsb,get_ch;
	timeout=200;

	MC12_ConfigMode(OS_SD_Single_Trans);	//配置单次测量
	MY_DELAY_MS(wait_time);
	__measure:
	MC1112_I2C_Receive(I2C_ADDR[1],STATUS,&sta);		
	timeout--;
	if(!((sta&0x30)==(get_ch>>6)<<4) && timeout>0) goto __measure;		//判断statu寄存器转换完成标志位

	MC1112_I2C_Receive(I2C_ADDR[1],DATA_CH0_MSB,&data_msb);
	I2C_Result = MC1112_I2C_Receive(I2C_ADDR[1],DATA_CH0_LSB,&data_lsb);
	if(I2C_Result != GPIOI2C_XFER_LASTNACK)return 0;
	*F0 = (float)(CLKIN*Fin_Div_VALUE/Fref_Div_VALUE*(data_msb<<8|data_lsb)/65535);//通道0频率计算公式,F=DATA0*Fin_Div*CLKIN/RCNT;DATA为通道0计数值，Fin_Div为输入频率分频，CLKIN为参考采样时钟，REV_RCNT为通道计数时间

	MC1112_I2C_Receive(I2C_ADDR[1],DATA_CH1_MSB,&data_msb);
	I2C_Result = MC1112_I2C_Receive(I2C_ADDR[1],DATA_CH1_LSB,&data_lsb);
	if(I2C_Result != GPIOI2C_XFER_LASTNACK)return 0;
	*F1 = (float)(CLKIN*Fin_Div_VALUE/Fref_Div_VALUE*(data_msb<<8|data_lsb)/65535);

	return 1;
}


/**-----------------------------------------------------------------------
  * @brief  MC1112数据发送函数
  * @param  DeviceAddr：地址  reg：寄存器地址  Data：发送数据
  * @retval 是否传输成功
-------------------------------------------------------------------------*/
I2C_Trans_Type MC1112_I2C_Transmit(uint8_t DeviceAddr, REG reg, uint8_t Data)
{
	I2C_Trans_Type ret=GPIOI2C_XFER_LASTACK;

	I2C_Start();

  	if(I2C_master_write((DeviceAddr<<1) & I2CWRITE_MASK)==GPIOI2C_NACK)
	{
		I2C_Stop();

		I2C_Start();
		if(I2C_master_write((DeviceAddr<<1) & I2CWRITE_MASK)==GPIOI2C_NACK)
		{
			I2C_Stop();
			return GPIOI2C_XFER_ADDRNACK;
		}
		
	}

	if(I2C_master_write(reg)==GPIOI2C_NACK)
	{
		I2C_Stop();
		return GPIOI2C_XFER_ABORTNACK;
	}

	if(I2C_master_write(Data)==GPIOI2C_NACK)
	{
		I2C_Stop();
		return GPIOI2C_XFER_ABORTNACK;
	}

	I2C_Stop();
	return ret;
}


/**-----------------------------------------------------------------------
  * @brief  MC1112数据接收函数
  * @param  DeviceAddr：地址  reg：寄存器地址  *pData：接收数据
  * @retval 是否传输成功
-------------------------------------------------------------------------*/
I2C_Trans_Type MC1112_I2C_Receive(uint8_t DeviceAddr, REG reg,uint8_t *pData)
{

	I2C_Start();

  	if(I2C_master_write((DeviceAddr<<1) & I2CWRITE_MASK)==GPIOI2C_NACK)
	{
		I2C_Stop();
		I2C_Start();
		if(I2C_master_write((DeviceAddr<<1) & I2CWRITE_MASK)==GPIOI2C_NACK)
		{
			I2C_Stop();
			return GPIOI2C_XFER_ADDRNACK;
		}
	}

	if(I2C_master_write(reg)==GPIOI2C_NACK)
	{
		I2C_Stop();
		return GPIOI2C_XFER_ABORTNACK;
	}

	I2C_reStart();

  if(I2C_master_write((DeviceAddr<<1) | I2CREAD_MASK)== GPIOI2C_NACK)
	{
		I2C_Stop();

		return GPIOI2C_XFER_ABORTNACK;
	}


	(*pData)=I2C_master_read(GPIOI2C_NACK);

	I2C_Stop();

	return GPIOI2C_XFER_LASTNACK;
}


/**-----------------------------------------------------------------------
  * @brief  log2函数，范围1-256
  * @param  DATA：2的N次幂
  * @retval 真数
-------------------------------------------------------------------------*/
uint8_t MC_Log2(uint32_t DATA)
{
	uint8_t ret = 0;
	switch (DATA)
	{
		case 1:
			ret = 0;
		break;
		case 2:
			ret = 1;
		break;
		case 4:
			ret = 2;
		break;
		case 8:
			ret = 3;
		break;
		case 16:
			ret = 4;
		break;
		case 32:
			ret = 5;
		break;
		case 64:
			ret = 6;
		break;
		case 128:
			ret = 7;
		break;
		case 256:
			ret = 8;
		break;
		default:
		break;
	}
	return ret;
}
/**-----------------------------------------------------------------------
  * @brief  POW2函数
  * @param  N：真数
  * @retval 2的N次幂
-------------------------------------------------------------------------*/

int MC_Pow2(uint8_t N)
{
	int ret = 0;
	switch (N)
	{
		case 0:
			ret = 1;
		break;
		case 1:
			ret = 2;
		break;
		case 2:
			ret = 4;
		break;
		case 3:
			ret = 8;
		break;
		case 4:
			ret = 16;
		break;
		case 5:
			ret = 32;
		break;
		case 6:
			ret = 64;
		break;
		case 7:
			ret = 128;
		break;
		case 8:
			ret = 256;
		break;
		default:
		break;
	}
	return ret;
}